# -*- coding: utf-8 -*-
import json
import logging

from django.views.decorators.http import require_GET, require_POST
from future.utils import raise_with_traceback

from api.lottery import LOTTERY_TYPE, ORDER_LOGIC, ORDER_HANDLER
from api.lottery import handler
from api.preset.handler import get_available_lottery_preset
from common.cache import redis_cache
from common.lottery import KEYWORD_TYPE_DCT, cyclical
from common.lottery import db as lottery_db
from common.lottery.cyclical.abstract.order import BatchOrderPayer, check_buy_list_activity_type, \
    check_buy_list_bet_type, check_user_is_virtual
from common.lottery.handler import smart_track_handler
from common.utils import exceptions as err
from common.utils.api import check_params, parse_common_params
from common.utils.api import token_required, parse_p
from common.utils.decorator import response_wrapper
from common.utils.exceptions import ParamError
from common.utils.limit import frequency_limit

_LOGGER = logging.getLogger('bigbang')
MAX_COUNT = 200
MIN_STOP_LOTTERY_SUPPORT_CVC = 20


@require_GET
@response_wrapper
def summarize(req):
    query_dct = req.GET.dict()
    p_param = parse_p(query_dct.get('p'))
    lottery_list = get_available_lottery_preset(p_param)
    data = handler.get_summary(lottery_list)
    return data


@require_GET
@response_wrapper
@token_required
def get_order_history_v2(req):
    params = req.GET.dict()
    check_params(params, ['start_date'], {
        'max_type': '4',
    }, param_type_dct={
        'max_type': int,
        'status': int,
    })
    page, size = parse_common_params(params)
    resp_items = handler.get_history_v2(req.user_id, params, page, size)
    return {'list': resp_items, 'page': page, 'size': len(resp_items)}


@require_GET
@response_wrapper
@token_required
def get_track_history_v2(req):
    params = req.GET.dict()
    check_params(params, ['start_date'], {
        'max_type': '4'
    }, param_type_dct={
        'max_type': int,
        'status': int
    })
    page, size = parse_common_params(params)
    resp_items = handler.get_history_v2(req.user_id, params, page, size, False)
    return {'list': resp_items, 'page': page, 'size': len(resp_items)}


@require_GET
@response_wrapper
@token_required
def get_order_history_by_type_v2(req, activity_type):
    if activity_type not in KEYWORD_TYPE_DCT:
        raise err.ParamError('activity_type invalid')
    activity_type = KEYWORD_TYPE_DCT[activity_type]
    params = req.GET.dict()
    page, size = parse_common_params(params)
    if activity_type in cyclical.CYCLICAL_TYPE:
        return handler.get_cyclical_order_history_v2(req.user_id, activity_type, page, size, params.get('track_id'))
    else:
        raise err.ServerError('not implement activity_type')


@require_GET
@response_wrapper
@token_required
def get_order_detail_by_type_v2(req, activity_type, order_id):
    if activity_type not in KEYWORD_TYPE_DCT:
        raise err.ParamError('activity_type invalid')
    activity_type = KEYWORD_TYPE_DCT[activity_type]
    if activity_type in cyclical.CYCLICAL_TYPE:
        return handler.get_cyclical_order_detail_v2(
            req.user_id, activity_type, long(order_id))
    else:
        raise err.ServerError('not implement activity_type')


@require_GET
@response_wrapper
@token_required
def get_track_detail_by_type_v2(req, activity_type, track_id):
    if activity_type not in KEYWORD_TYPE_DCT:
        raise err.ParamError('activity_type invalid')
    activity_type = KEYWORD_TYPE_DCT[activity_type]
    if activity_type in cyclical.CYCLICAL_TYPE:
        return handler.get_cyclical_track_detail_v2(req.user_id, activity_type, track_id)
    else:
        raise err.ServerError('not implement activity_type')


@require_GET
@response_wrapper
def get_latest_term_by_type(req, activity_type):
    if activity_type not in KEYWORD_TYPE_DCT:
        raise err.ParamError('activity_type invalid')
    activity_type = KEYWORD_TYPE_DCT[activity_type]

    p = parse_p(req.GET.get('p'))
    cvc = p.get('cvc')
    chn = p.get('chn')
    if (lottery_db.check_stop_lottery(activity_type, chn, cvc)):
        _LOGGER.error("activity currently stopped: %s", activity_type)
        if cvc and int(cvc) >= MIN_STOP_LOTTERY_SUPPORT_CVC:
            raise err.InvalidLottery()
        raise err.NoTerm()

    if activity_type in cyclical.CYCLICAL_TYPE:
        return handler.get_cyclical_latest_activity(activity_type)
    else:
        raise err.ServerError('not implement activity_type')


@require_GET
@response_wrapper
def get_activity_history_by_type(req, activity_type):
    if activity_type not in KEYWORD_TYPE_DCT:
        raise err.ParamError('activity_type invalid')
    activity_type = KEYWORD_TYPE_DCT[activity_type]
    params = req.GET.dict()
    try:
        last_n = params.get('last_n')
        sort = params.get('sort')
        if last_n is not None:
            last_n = int(last_n)
            if last_n < 0 or last_n > MAX_COUNT:
                last_n = MAX_COUNT
        page, size = parse_common_params(params)
        status = params.get('status')
        if status is not None:
            status = status.split(',')
            status = [int(s) for s in status]
    except Exception:
        raise err.ParamError()
    if activity_type in cyclical.CYCLICAL_TYPE:
        resp_items = handler.get_cyclical_activity_history(
            activity_type, last_n, status, page, size, sort)
    else:
        raise err.ServerError('not implement activity_type')

    return {'list': resp_items, 'page': page, 'size': len(resp_items)}


@require_GET
@response_wrapper
def get_activity_stats_by_bet_type(req, activity_type, bet_type):
    if activity_type not in KEYWORD_TYPE_DCT:
        raise err.ParamError('activity_type invalid')
    activity_type = KEYWORD_TYPE_DCT[activity_type]
    return handler.get_stats(int(activity_type), bet_type)


@require_GET
@response_wrapper
@token_required
def get_user_read_stats(req):
    return handler.get_read_stats(req.user_id)


@require_GET
@response_wrapper
@token_required
def get_pay_history(req):
    user_id = req.user_id
    params = req.GET.dict()
    page, size = parse_common_params(params)

    ret, total = handler.get_pay_record_list(user_id, page, size)
    return dict(ret=ret, page=page, size=size, total=total)


def fix_term_number(activity_type, buy_list):
    term_size = max_term = tail_len = 0
    if activity_type == LOTTERY_TYPE.CQ_SSC:
        term_size, max_term, tail_len = 11, 120, 3
    elif activity_type == LOTTERY_TYPE.TJ_SSC:
        term_size, max_term, tail_len = 11, 84, 3
    elif activity_type == LOTTERY_TYPE.XJ_SSC:
        term_size, max_term, tail_len = 11, 96, 3
    elif activity_type == LOTTERY_TYPE.JS_KS:
        term_size, max_term, tail_len = 10, 82, 3
    elif activity_type == LOTTERY_TYPE.GX_KS:
        term_size, max_term, tail_len = 11, 78, 3
    elif activity_type == LOTTERY_TYPE.SH_11X5:
        term_size, max_term, tail_len = 10, 90, 2
    elif activity_type == LOTTERY_TYPE.GD_11X5:
        term_size, max_term, tail_len = 10, 84, 2
    elif activity_type == LOTTERY_TYPE.SD_11X5:
        term_size, max_term, tail_len = 10, 87, 2
    elif activity_type == LOTTERY_TYPE.JX_11X5:
        term_size, max_term, tail_len = 10, 84, 2
    elif activity_type == LOTTERY_TYPE.CQ_LF:
        term_size, max_term, tail_len = 11, 97, 3
    elif activity_type == LOTTERY_TYPE.FF_SSC:
        term_size, max_term, tail_len = 12, 1440, 4
    elif activity_type == LOTTERY_TYPE.FF_11X5:
        term_size, max_term, tail_len = 12, 1440, 4
    elif activity_type == LOTTERY_TYPE.FF_KS:
        term_size, max_term, tail_len = 12, 1440, 4
    elif activity_type == LOTTERY_TYPE.FF_PK10:
        term_size, max_term, tail_len = 12, 1440, 4
    if max_term and tail_len:
        for item in buy_list:
            term = item.get('term', '')
            # patch FIXME
            if activity_type in (LOTTERY_TYPE.XJ_SSC, LOTTERY_TYPE.CQ_LF, LOTTERY_TYPE.JS_KS) and len(term) == 10:
                item['term'] = term[:-2] + term[-2:].zfill(tail_len)
            if activity_type in (LOTTERY_TYPE.GD_11X5, LOTTERY_TYPE.SD_11X5) and len(term) == 12:
                item['term'] = term[:-2] + term[-2:].zfill(tail_len)

            if term[-tail_len:] == '0' * tail_len:
                item['term'] = term[:-tail_len] + str(max_term).zfill(tail_len)


@require_POST
@response_wrapper
@token_required
@frequency_limit
def order_pay(req):
    user_id = req.user_id
    params = json.loads(req.body)
    check_params(params, ['buy_list'])
    buy_list = params['buy_list']
    activity_type = check_buy_list_activity_type(buy_list)
    off = redis_cache.get_activity_switch(activity_type)
    if off:
        _LOGGER.warn('activity %s has been turned down, stop pay!', activity_type)
        raise err.PermissionError(u'当前彩种无法购买')
    bet_type_list = check_buy_list_bet_type(buy_list)
    fix_term_number(activity_type, buy_list)
    coupon_id = params.get('coupon')
    smart_track = params.get('smart_track')
    is_track = False
    handler = ORDER_HANDLER[activity_type]
    logic = ORDER_LOGIC[activity_type]
    if smart_track:
        fix_term_number(activity_type, smart_track)
        total_count, total_amount = 0, 0
        for item in buy_list:
            handler.check_order_params(item)
            count, amount = smart_track_handler(user_id, activity_type, item, smart_track, logic)
            total_count += count
            total_amount += amount
        return {'total_count': total_count, 'total_amount': total_amount}

    valid_buy_list = []
    for item in buy_list:
        handler.check_order_params(item)
        item['price'] = logic.calc_total_price(item['bet_type'], item['number'], item['times'], item['unit'])
        if item['price'] > 0:
            valid_buy_list.append(item)
        else:
            continue
        if int(item.get('term_count')) != 1:
            is_track = True
    if not valid_buy_list:
        raise err.ParamError(u'无效注单')
    # 不使用红包或追号情况下使用旧的create_order方法，使用红包就使用新的create_order方法
    if is_track or not coupon_id:
        total_count, total_amount = 0, 0
        for item in valid_buy_list:
            count, amount = handler.create_order(user_id, item)
            total_count += count
            total_amount += amount
        return {'total_count': total_count, 'total_amount': total_amount}
    else:
        is_virtual = check_user_is_virtual(user_id)
        for bet_type in bet_type_list:
            order_payer = BatchOrderPayer(activity_type, user_id, coupon_id, valid_buy_list, bet_type, is_virtual)
        total_count, total_amount = order_payer.batch_pay()
    return {'total_count': total_count, 'total_amount': total_amount}


@require_GET
@token_required
@response_wrapper
def get_order_wait_show(request):
    # 获取未晒单的列表
    try:
        page = int(request.GET.get('page', 0))
        size = int(request.GET.get('size', 0))
    except Exception as e:
        raise_with_traceback(ParamError(e))

    orders = handler.view_wait_show_orders(request.user_id, page=page, size=size)
    order_lites = handler.create_wait_show_order_lite(orders)

    return {
        'list': order_lites,
        'page': page if page > 0 else 1,
        'size': len(order_lites)
    }


@require_GET
@response_wrapper
@token_required
def get_order_detail_by_type_v3(req, activity_type, order_id):
    activity_type = int(activity_type)
    if activity_type in cyclical.CYCLICAL_TYPE:
        return handler.get_cyclical_order_detail_v3(
            req.user_id, activity_type, long(order_id))
    else:
        raise err.ServerError('not implement activity_type')
